#pragma once

#include <MCF/Code/StdMCF.hpp>

class SDCardClass sealed : NO_COPY_OR_ASSIGN {
private:
	class _SDCardThreadClass;
private:
	static const std::size_t _SECTOR_SIZE = 0x200;

	typedef enum : DWORD {
		OP_NONE,
		OP_MOUNT,
		OP_UNMOUNT,
		OP_READ,
		OP_WRITE
	} _LAST_OPERATION;
private:
	static bool _EventSDMountProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
	static bool _EventSDInitializeProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
	static bool _EventSDReadRequestProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
	static bool _EventSDWriteRequestProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
	static bool _EventSDQueryStatusProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
	static bool _EventSDGetErrorCodeProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
	static bool _EventSDSnapshotProc(std::intptr_t nContext, std::intptr_t nArg1, std::intptr_t nArg2, std::intptr_t nArg3);
private:
	_SDCardThreadClass *_m_lpSDCardThread;

	HANDLE _m_hMountedFile;
	long long _m_llCapacity;
	_LAST_OPERATION _m_eLastOperation;
	std::size_t _m_uLastSectorID;

	mutable DWORD _m_dwErrorCode;
public:
	SDCardClass();
	~SDCardClass();
public:
	void MountFile(LPCTSTR lpszPath);
	void MountDrive(int nDriveIndex);
	void Unmount();
	bool IsMounted() const;

	DWORD GetErrorCode() const;

	bool IsIdle() const;
	void Wait() const;
	void WaitTimeout(DWORD dwMilliSeconds) const;

	void Initialize();
	DWORD QueryStatus() const;

	bool ReadSector(std::size_t uSectorID, BYTE *lpbyBuffer);
	bool WriteSector(std::size_t uSectorID, const BYTE *lpbyBuffer);
	DWORD Snapshot(std::size_t uSectorID, BYTE *lpbyBuffer) const;
};
